﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.Serialization;
using System.IO;
using System.Runtime.Serialization.Formatters;
using ProtoBuf;
using SharpDX;
using SharpDX.DXGI;
using System.Collections.ObjectModel;


namespace Engine
{
    public partial class StartForm : Form
    {
        public Config config = new Config();
        public List<DisplayMode> LDM = new List<DisplayMode> { };

        public StartForm()
        {
            this.BackgroundImage = null;
            bool FileFail = false;
            InitializeComponent();
            FileStream fs = null;
            try
            {
                fs = new FileStream("Config.bin", FileMode.Open, FileAccess.Read);
                config = Serializer.Deserialize<Config>(fs);
                fs.Close();
            }
            catch(Exception ex)
            {
                FileFail = true;
                if (fs != null) fs.Close();
                System.Windows.Forms.MessageBox.Show("Error! Небыл найден файл настроек\n" + ex.Message);
            }

            ModeDescription[] DML = null;


            using (SharpDX.DXGI.Factory myFactory = new SharpDX.DXGI.Factory())
            {

                int MyAdapterCount = myFactory.GetAdapterCount();
                try
                {
                    using (SharpDX.DXGI.Adapter MyAdapter = myFactory.GetAdapter(MyAdapterCount - 1))
                    {
                        using (Output OP = MyAdapter.Outputs[0])
                            DML = OP.GetDisplayModeList(Format.R8G8B8A8_UNorm, DisplayModeEnumerationFlags.Interlaced);
                    }

                }
                catch (System.Exception ex)
                {
                    using (SharpDX.DXGI.Adapter MyAdapter = myFactory.GetAdapter(MyAdapterCount - 0))
                    {
                        using (Output OP = MyAdapter.Outputs[0])
                            DML = OP.GetDisplayModeList(Format.R8G8B8A8_UNorm, DisplayModeEnumerationFlags.Interlaced);
                    }
                }
            }

            int mw = 0, mh = 0;
            foreach (ModeDescription dm in DML)
            {
                bool cor = true;
                foreach (DisplayMode dmd in LDM)
                {
                    if (dmd.Width == dm.Width && dmd.Height == dm.Height)
                    {
                        cor = false;
                    }
                }

                if (cor && dm.Width >= 1024 && dm.Height >= 768)
                    LDM.Add(new DisplayMode(dm.Width, dm.Height));

                if (dm.Width > mw) mw = dm.Width;
                if (dm.Height > mh) mh = dm.Height;
            }
            
            if (LDM.Count < 1)
            {
                System.Windows.Forms.MessageBox.Show("Error! Минимальное поддерживаемое разрешение экрана 1024х768");
                this.Close();
            }

            if (config.Width > mw || config.Height > mh)
            {
                FileFail = true;
            }
            
            if (GetResIndex(config.Width, config.Height, LDM) < 0)
                FileFail = true;
            
            if (FileFail)
            {
                config = new Config();
                SaveC(config, "Config.bin");
            }
            SetData();

            for (int num = 0; num < LDM.Count; num++)
            {
                comboBox1.Items.Add(LDM[num].Width.ToString() + "x" + LDM[num].Height.ToString());
            }


            int Res = GetResIndex(config.Width, config.Height, LDM);

            if (Res > -1)
            {
                comboBox1.SelectedIndex = Res;
            }

            if (config.VSync>0)
            {
                checkBox1.Checked = true;
            }
            else
            {
                checkBox1.Checked = false;
            }

            if (config.InvAlt > 0)
            {
                checkBox3.Checked = true;
            }
            else
            {
                checkBox3.Checked = false;
            }

            comboBox2.Items.Add("High");
            comboBox2.Items.Add("Medium");
            comboBox2.Items.Add("Low");
            comboBox2.Items.Add("Disable");


            if (config.Shadow < 1)
            {
                comboBox2.SelectedIndex = 3;
            }
            else
            {
                comboBox2.SelectedIndex = config.ShadowQuality;
            }

            comboBox3.Items.Add("Disable");
            comboBox3.Items.Add("Low");
            comboBox3.Items.Add("Medium");
            comboBox3.Items.Add("High");

            if (config.MultiSample > -1 && config.MultiSample < 2)
            {
                comboBox3.SelectedIndex = 0;
            }
            if (config.MultiSample > 1 && config.MultiSample < 4)
            {
                comboBox3.SelectedIndex = 1;
            }
            if (config.MultiSample > 3 && config.MultiSample < 8)
            {
                comboBox3.SelectedIndex = 2;
            }
            if (config.MultiSample > 7)
            {
                comboBox3.SelectedIndex = 3;
            }

            comboBox4.Items.Add("Disable");
            comboBox4.Items.Add("4");
            comboBox4.Items.Add("8");
            comboBox4.Items.Add("12");

            if (config.Light > -1 && config.Light < 4)
            {
                comboBox4.SelectedIndex = 0;
            }
            if (config.Light > 3 && config.Light < 7)
            {
                comboBox4.SelectedIndex = 1;
            }
            if (config.Light > 7 && config.Light < 11)
            {
                comboBox4.SelectedIndex = 2;
            }
            if (config.Light > 11)
            {
                comboBox4.SelectedIndex = 3;
            }

            if (config.FullScr > 0)
            {
                checkBox2.Checked = true;
            }
            else
            {
                checkBox2.Checked = false;
            }

            if (config.Refract > 0)
            {
                checkBox4.Checked = true;
            }
            else
            {
                checkBox4.Checked = false;
            }
        }


        /// <summary>
        /// Сохранить
        /// </summary>
        public void SaveC(object obj, string name)
        {
            FileStream fs = new FileStream(name, FileMode.Create);
            Serializer.Serialize(fs, obj);
            fs.Close();
        }
        [ProtoContract]
        public class Config
        {
            [ProtoMember(1)]
            public int Width = 1024;
            [ProtoMember(2)]
            public int Height = 768;
            [ProtoMember(3)]
            public int MultiSample = 0;
            [ProtoMember(4)]
            public int ShadowQuality = 1;
            [ProtoMember(5)]
            public int Shadow = 1;
            [ProtoMember(6)]
            public int VSync = 0;
            [ProtoMember(7)]
            public int FullScr = 0;
            [ProtoMember(8)]
            public int InvAlt = 0;
            [ProtoMember(9)]
            public int Refract = 0;
            [ProtoMember(10)]
            public int Light = 0;
        }

        public void SetData()
        {
            Global.Settings.Width = config.Width;
            Global.Settings.Height = config.Height;
            Global.Settings.ShadowQuality = config.ShadowQuality;
            Global.Settings.MultiSample = config.MultiSample;
            if (config.VSync>0)
                Global.Settings.VSync = 1;
            else
                Global.Settings.VSync = 0;

            if (config.Shadow > 0)
                Global.Settings.Shadow = true;
            else
                Global.Settings.Shadow = false;

            if (config.FullScr > 0)
                Global.Settings.FullScr = true;
            else
                Global.Settings.FullScr = false;

            if (config.InvAlt > 0)
                Global.Settings.InvAlt = true;
            else
                Global.Settings.InvAlt = false;

            if (config.Refract > 0)
                Global.Settings.Refract = true;
            else
                Global.Settings.Refract = false;

            Global.Settings.Light = config.Light;

            SaveC(config, "Config.bin");
        }
        
        public int GetResIndex(int W, int H, List<DisplayMode> LDM_)
        {
            for (int num = 0; num < LDM_.Count; num++)
            {
                if (LDM_[num].Width == W && LDM_[num].Height == H)
                    return num;
            }
            return -1;
        }
        
        private void button1_Click(object sender, EventArgs e)
        {
            Global.Settings.Run = true;
            this.Close();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            LDM.Clear();

            ModeDescription[] DML = null;
            using (SharpDX.DXGI.Factory myFactory = new SharpDX.DXGI.Factory())
            {

                int MyAdapterCount = myFactory.GetAdapterCount();
                try
                {
                    using (SharpDX.DXGI.Adapter MyAdapter = myFactory.GetAdapter(MyAdapterCount - 1))
                    {
                        using (Output OP = MyAdapter.Outputs[0])
                            DML = OP.GetDisplayModeList(Format.R8G8B8A8_UNorm, DisplayModeEnumerationFlags.Interlaced);
                    }

                }
                catch (System.Exception ex)
                {
                    using (SharpDX.DXGI.Adapter MyAdapter = myFactory.GetAdapter(MyAdapterCount - 0))
                    {
                        using (Output OP = MyAdapter.Outputs[0])
                            DML = OP.GetDisplayModeList(Format.R8G8B8A8_UNorm, DisplayModeEnumerationFlags.Interlaced);
                    }
                }
            }

            foreach (ModeDescription dm in DML)
            {
                bool cor = true;
                foreach (DisplayMode dmd in LDM)
                {
                    if (dmd.Width == dm.Width && dmd.Height == dm.Height)
                    {
                        cor = false;
                    }
                }

                if (cor && dm.Width >= 1024 && dm.Height >= 768)
                    LDM.Add(new DisplayMode(dm.Width, dm.Height));
            }

            config.Width = LDM[comboBox1.SelectedIndex].Width;
            config.Height = LDM[comboBox1.SelectedIndex].Height;
            SetData();
        }

        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBox1.Checked)
            {
                config.VSync = 1;
                SetData();
            }
            else
            {
                config.VSync = 0;
                SetData();
            }
        }

        private void comboBox2_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (comboBox2.SelectedIndex == 3)
            {
                config.Shadow = 0;
            }
            else
            {
                config.Shadow = 1;
                config.ShadowQuality = comboBox2.SelectedIndex;
            }
            SetData();
        }

        private void comboBox3_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (comboBox3.SelectedIndex == 0)
                config.MultiSample = 0;
            if (comboBox3.SelectedIndex == 1)
                config.MultiSample = 2;
            if (comboBox3.SelectedIndex == 2)
                config.MultiSample = 4;
            if (comboBox3.SelectedIndex == 3)
                config.MultiSample = 8;
            SetData();
        }

        private void checkBox2_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBox2.Checked)
            {
                config.FullScr = 1;
                SetData();
            }
            else
            {
                config.FullScr = 0;
                SetData();
            }
        }

        private void checkBox3_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBox3.Checked)
            {
                config.InvAlt = 1;
                SetData();
            }
            else
            {
                config.InvAlt = 0;
                SetData();
            }
        }

        private void checkBox4_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBox4.Checked)
            {
                config.Refract = 1;
                SetData();
            }
            else
            {
                config.Refract = 0;
                SetData();
            }
        }

        private void comboBox4_SelectedIndexChanged_1(object sender, EventArgs e)
        {
            if (comboBox4.SelectedIndex == 0)
                config.Light = 0;
            if (comboBox4.SelectedIndex == 1)
                config.Light = 4;
            if (comboBox4.SelectedIndex == 2)
                config.Light = 8;
            if (comboBox4.SelectedIndex == 3)
                config.Light = 12;
            SetData();
        }
        
    }

    public class DisplayMode
    {
        public int Width = 0;
        public int Height = 0;

        public DisplayMode(int Width, int Height)
        {
            this.Width = Width;
            this.Height = Height;
        }
    }
}
